#include "WorkTask.h"

#include "Logger.h"
#include "Singleton.h"
#include "SocketHandler.h"
#include "Workflow.h"

#include <sstream>

using namespace ddserver::socket;
using namespace ddserver::engine;
using namespace ddserver::task;
using namespace ddserver::utility;

using std::ostringstream;

void deleteMem(char* p)
{      
    if(p)
    {
        delete []p;
        p = NULL;
    }
}

WorkTask::WorkTask(Socket * socket,int servertype) : Task(socket),m_serverType(servertype)
{
}

WorkTask::~WorkTask()
{
}

void WorkTask::run()
{
    log_debug("work task run");
    SocketHandler * handler = Singleton<SocketHandler>::instance();

    Socket * socket = static_cast<Socket *>(m_data);

    MsgHead msg_head;
    memset(&msg_head, 0, sizeof(msg_head));
    int len = socket->recv((char *)(&msg_head), sizeof(msg_head));
    if (len == 0)
    {
        log_error("socket closed by peer");
        handler->remove(socket);
        return;
    }
    if (len == -1 && errno == EAGAIN)
    {
        log_error("socket recv len: %d, log_error msg: EAGAIN errno: %d", len, errno);
        handler->attach(socket);
        return;
    }
    if (len == -1 && errno == EWOULDBLOCK)
    {
        log_error("socket recv len: %d, log_error msg: EWOULDBLOCK errno: %d", len, errno);
        handler->attach(socket);
        return;
    }
    if (len == -1 && errno == EINTR)
    {
        log_error("socket recv len: %d, log_error msg: EINTR errno: %d", len, errno);
        handler->attach(socket);
        return;
    }
    if (len != sizeof(msg_head))
    {
        log_error("recv msg head log_error length: %d, errno: %d", len, errno);
        handler->remove(socket);
        return;
    }
    log_info("[len:%d,flag:%s,cmd:%d,body_len:%d]recv msg head", len, msg_head.flag, msg_head.cmd, msg_head.len);
    if (strncmp(msg_head.flag, "work", 4) != 0)
    {
        log_error("msg head flag log_error[err_flag=%s]",msg_head.flag);
        handler->remove(socket);
        return;
    }

    int bufLen = msg_head.len;
    char* buf = new char[bufLen + 1];
    if (buf == NULL)
    {
        log_error("can not new some memory");
        return;
    }
    
    memset(buf, 0, bufLen + 1);
    len = socket->recv(buf, msg_head.len);
    if (len == -1 && errno == EAGAIN)
    {
        log_error("socket recv len: %d, log_error msg: EAGAIN errno: %d", len, errno);
        handler->remove(socket);
        deleteMem(buf);
        return;
    }
    if (len == -1 && errno == EWOULDBLOCK)
    {
        log_error("socket recv len: %d, log_error msg: EWOULDBLOCK errno: %d", len, errno);
        handler->remove(socket);
        deleteMem(buf);
        return;
    }
    if (len == -1 && errno == EINTR)
    {
        log_error("socket recv len: %d, log_error msg: EINTR errno: %d", len, errno);
        handler->remove(socket);
        deleteMem(buf);
        return;
    }
    if (len != (int)(msg_head.len))
    {
        log_error("recv msg body log_error length: %d, body: %s, errno: %d", len, buf, errno);
        handler->remove(socket);
        deleteMem(buf);
        return;
    }

    log_info("[len:%d,msg_data:%s]recv msg body",len, buf);

    if(m_serverType == 1)
    {
        Workflow* workflow = Singleton<Workflow>::instance();

        ostringstream os_cmd; 
        os_cmd << (int)(msg_head.cmd); 
        const string workCmd = os_cmd.str();
        const string input = buf;
        string output;
        workflow->run(workCmd, input, output);
        socket->send(output.c_str(), output.length());
    }

    handler->attach(socket);
    deleteMem(buf);

    return;
}

void WorkTask::destroy()
{
    log_debug("work job destory");
    delete this;
}
